package cn.tannn.tcache.core;

import cn.tannn.tcache.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 命令
 *
 * @author <a href="https://t.tannn.cn/">tnnn</a>
 * @version V1.0
 * @date 2024/6/19 下午8:12
 */
public interface Command {
    Logger log = LoggerFactory.getLogger(Command.class);
    /**
     * RESP支持如下几个数据类型: Simple Strings, Errors, Integers, Bulk Strings, and Arrays.
     * Redis的请求和响应里，客户端Client发送命令的格式为Bulk Strings的数组Array。
     * 服务端Server返回的响应信息则根据不同的结果类型而不同。
     * 协议的首个字节决定了数据类型：
     *  Simple Strings, 第一个字节是 "+"
     *  Errors, 第一个字节是 "-"
     *  Integers, 第一个字节是 ":"
     *  Bulk Strings, 第一个字节是 "$"
     *  Arrays, 第一个字节是 "*"
     * 协议使用特殊的Bulk Strings 或 Array 来表示Null空值。
     * 协议的不同部分，使用 "\r\n" (CRLF) 作为分隔符
     */
    String CRLF = "\r\n";
    String STR_PREFIX = "+";
    String BULK_PREFIX = "$";
    String OK = "OK";

    /**
     * 命令名
     *
     * @return name
     */
    String name();

    /**
     * 解析命令并响应结果值
     *
     * @param cache cache
     * @param args  command arguments
     * @return Reply
     */
    Reply<?> exec(Tcache cache, String[] args);

    /**
     * 只有一个key
     * @param args command arguments
     * @return key
     */
    default String getKey(String[] args){
        try {
            return args[4];
        }catch (Exception e){
            log.error("Error getting key, key is empty");
           return null;
        }
    }

    /**
     * 只有一个value
     * @param args command arguments
     * @return value
     */
    default String getVal(String[] args){
        try {
            return args[6];
        }catch (Exception e){
            log.error("Error getting val, val is empty");
            return null;
        }
    }

    default String[] getHvals(String[] args) {
        int len = (args.length - 5) / 4;
        String[] vals = new String[len];
        for (int i = 0; i < len; i++) {
            vals[i] = args[8 + i * 4];
        }
        return vals;
    }

    default String[] getHkeys(String[] args) {
        int len = (args.length - 5) / 4;
        String[] keys = new String[len];
        for (int i = 0; i < len; i++) {
            keys[i] = args[6 + i * 4];
        }
        return keys;
    }

    /**
     * 去掉key以外的其他所有的值参数
     * <p> e.g.  k1 v1 v2 v3 v4 v5 v6
     * @param args command arguments [k1 v1 v2 v3 v4 v5 v6]
     * @return vals [v1 v2 v3 v4 v5 v6]
     */
    default String[] getParamsNoKey(String[] args) {
       try {
           int len = (args.length-5)/2;
           String[] keys = new String[len];
           for(int i=0; i<len; i++) {
               keys[i] = args[6+i*2];
           }
           return keys;
       }catch (Exception e){
           log.error("Error getting val, val is empty");
           return new String[0];
       }
    }

    /**
     * 解析命令行的keys
     *
     * @param args args
     * @return keys
     */
    default String[] genKeys(String[] args) {
        // 去掉前三个系统参数，在去掉一般的长度变量 = 真实key数量
        int len = (args.length - 3) / 2;
        String[] keys = new String[len];
        for (int i = 0; i < len; i++) {
            // 从第四个开每隔两位取一个，取真实的key数据
            keys[i] = args[4 + i * 2];
        }
        return keys;
    }


    /**
     * 解析命令行的[key val]
     * @param args args
     * @return key,val
     */
    default Pair<String[], String[]> genKeyVal(String[] args) {
        int len = (args.length - 3) / 4;
        String[] keys = new String[len];
        String[] vals = new String[len];
        for (int i = 0; i < len; i++) {
            keys[i] = args[4 + i * 4];
            vals[i] = args[6 + i * 4];
        }
        return new Pair<>(keys, vals);
    }
}
